package com.ly.common.utils.erp;

import com.alibaba.fastjson.JSONArray;
import com.ly.common.enums.CalculateStatus;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Author: Wuzh
 * @Description: 工具类
 * @Date Created in 13:46 2020/9/10
 * @return
 */
public class CommonUtil {


    public static final SimpleDateFormat sdf = new SimpleDateFormat ( "yyyyMMdd" );


    public static String getCurrentSimpleDate () {
        return sdf.format ( Calendar.getInstance ().getTime () );
    }


    public static Date getCurrDate ( int isMin ) {
        SimpleDateFormat sdFormat = null;
        if ( isMin == 1 ) {
            sdFormat = new SimpleDateFormat ( "yyyy-MM-dd HH:mm:ss SSS" );
        } else {
            sdFormat = new SimpleDateFormat ( "yyyy-MM-dd HH:mm:ss" );
        }
        Date date = new Date ();
        String dateString = sdFormat.format ( date );
        ParsePosition pos = new ParsePosition ( 0 );
        Date currentTime_2 = sdFormat.parse ( dateString, pos );
        return currentTime_2;
    }

    /**
     * 将时间转化成指定格式-Date-String
     *
     * @param date
     * @param format
     * @return String
     */
    public static String getDateStrFormat ( Date date, String format ) {
        String reString = "";
        try {
            SimpleDateFormat sdFormat = new SimpleDateFormat ( format );
            //Date date = sdFormat.parse(orDate);
            reString = sdFormat.format ( date );
        } catch ( Exception e ) {
            // TODO: handle exception
        }
        return reString;
    }


    /**
     * @return
     * @Author: Wuzh
     * @Description: 获取系统当前格式化时间
     */
    public static String getFormatDateTime ( String format ) {
        LocalDateTime localDateTime = LocalDateTime.now ();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern ( format );
        return dateTimeFormatter.format ( localDateTime );
    }


    /**
     * LocalDate转Date
     *
     * @param localDateTime
     * @return
     */
    public static Date format ( LocalDateTime localDateTime ) {
        ZoneId zoneId = ZoneId.systemDefault ();
        ZonedDateTime zdt = localDateTime.atZone ( zoneId );
        Date date = Date.from ( zdt.toInstant () );
        return date;
    }

    /**
     * Date转LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime parseToDate ( Date date ) {
        ZoneId zoneId = ZoneId.systemDefault ();
        LocalDateTime localDateTime = LocalDateTime.ofInstant ( date.toInstant (), zoneId );
        return localDateTime;
    }


    /**
     * 计算两个时间相差多少天
     *
     * @param startTime：开始日期
     * @param endTime：结束日期
     * @return：大于0表示正常，小于0表示逾期，计算实际逾期天数
     */
    public static int timeDifferenceDay ( Date startTime, Date endTime ) {
        long start = startTime.getTime ();
        long end = endTime.getTime ();
        long time = end - start;
        int day = ( int ) ( time / 24 / 60 / 60 / 1000 );
        return day;
    }

    public static Date parseDate ( String date ) throws ParseException {
        if ( date == null || "".equals ( date ) ) {
            return new Date ();
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat ("yyyy-MM-dd'T'");
        Date parse = simpleDateFormat.parse ( date );
        return parse;
    }

    /**
     * 获取给定长度的随机整数
     *
     * @param length 长度
     * @return
     */
    public static String getInviteCode ( int length ) {
        StringBuilder sb = new StringBuilder ();
        Random random = new Random ();
        char arrays[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
        for ( int i = 0; i < length; i++ ) {
            sb.append ( arrays[random.nextInt ( arrays.length )] );
        }
        return sb.toString ();
    }

    /**
     * 求两个小数之和并保留两位小数
     *
     * @param dAdd2
     * @param dAdd2
     * @return
     */
    public static double sum ( double dAdd1, double dAdd2 ) {
        DecimalFormat df = new DecimalFormat ( "#.00" );
        double sum = dAdd1 + dAdd2;
        return Double.valueOf ( df.format ( sum ) );
    }


    /**
     * 将字符串类型小数，保留两位小数
     *
     * @param str
     * @param digit
     * @return
     */
    public static String stringPoint ( String str, int digit ) {
        if ( StringUtils.isBlank ( str ) ) {
            return "0";
        }
        BigDecimal bd = new BigDecimal ( str );
        bd = bd.setScale ( digit, RoundingMode.HALF_UP ); // 设置小数点后两位，并进行四舍五入
        String formattedValue = bd.toString ();
        return formattedValue;
    }


    /**
     * 将字符串类型小数，保留两位小数
     *
     * @param value
     * @return
     */
    public static String doublePoint ( double value, int digit ) {
        if ( value == 0 ) {
            return "0";
        }
        BigDecimal bd = new BigDecimal ( value );
        bd = bd.setScale ( digit, RoundingMode.HALF_UP ); // 设置小数点后两位，并进行四舍五入
        String formattedValue = bd.toString ();
        return formattedValue;
    }


    /**
     * 求两位字符串类型的数据之和，并返回指定长度小数点后以字符串形式返回
     *
     * @param add1：加数1
     * @param add2：加数2
     * @param digit：保留小数点位数
     * @return
     */
    public static String sumStr ( String add1, String add2, int digit ) {
        if ( StringUtils.isBlank ( add1 ) || StringUtils.isBlank ( add2 ) ) {
            return "0";
        }
        double v1 = Double.parseDouble ( add1 );
        double v2 = Double.parseDouble ( add2 );
        BigDecimal bd = BigDecimal.valueOf ( v1 + v2 ).setScale ( digit, RoundingMode.HALF_UP );
        double roundedValue = bd.doubleValue ();
        String result = String.valueOf ( roundedValue );
        return result;
    }

    /**
     * 求两位字符串类型的数据之差，并返回指定长度小数点后以字符串形式返回
     *
     * @param sub1：减数1
     * @param sub2：减数2
     * @param digit：保留小数点位数
     * @return
     */
    public static String subStr ( String sub1, String sub2, int digit ) {
        if ( StringUtils.isBlank ( sub1 ) || StringUtils.isBlank ( sub2 ) ) {
            return "0";
        }
        double v1 = Double.parseDouble ( sub1 );
        double v2 = Double.parseDouble ( sub2 );
        BigDecimal bd = BigDecimal.valueOf ( v1 - v2 ).setScale ( digit, RoundingMode.HALF_UP );
        double roundedValue = bd.doubleValue ();
        String result = String.valueOf ( roundedValue );
        return result;
    }


    /**
     * 计算两个字符串类型的小数乘积，当结果小数位大于2时，保留2位；当结果小数位小于2时，保留原来的
     *
     * @param multiplier
     * @param multiplicand
     * @param digit
     * @return
     */
    public static String rideStr ( String multiplier, String multiplicand, int digit ) {
        if ( StringUtils.isBlank ( multiplier ) || StringUtils.isBlank ( multiplicand ) ) {
            return "0.0";
        }
        double dMultiplier = Double.valueOf ( multiplier );
        double dMultiplicand = Double.valueOf ( multiplicand );
        BigDecimal bd = BigDecimal.valueOf ( dMultiplier * dMultiplicand ).setScale ( digit, RoundingMode.HALF_UP );
        double roundedValue = bd.doubleValue ();
        String result = String.valueOf ( roundedValue );
        return result;
    }

    /**
     * 求除法，保留digit个小数位，并返回计算结果
     *
     * @param divisor：除数
     * @param dividend：被除数
     * @param digit：要保留的小数点位数
     * @return
     */
    public static String divisionStr ( String divisor, String dividend, int digit ) {
        if ( StringUtils.isBlank ( divisor ) || StringUtils.isBlank ( dividend ) || digit < 0 ) {
            return "0";
        }
        double vDiv = Double.parseDouble ( divisor );
        double vDid = Double.parseDouble ( dividend );
        if ( vDid == 0 ) {
            return "0";
        }
        BigDecimal bd = BigDecimal.valueOf ( vDiv / vDid ).setScale ( digit, RoundingMode.HALF_UP );
        double roundedValue = bd.doubleValue ();
        String result = String.valueOf ( roundedValue );
        return result;
    }


    /**
     * 判断两个Date类型的日期是否为同一个月
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean checkSameMonth ( Date date1, Date date2 ) {
        if ( date1 == null || date2 == null ) {
            return false;
        }
        Calendar cal1 = Calendar.getInstance ();
        Calendar cal2 = Calendar.getInstance ();
        cal1.setTime ( date1 );
        cal2.setTime ( date2 );
        return ( cal1.get ( Calendar.YEAR ) == cal2.get ( Calendar.YEAR ) ) &&
                ( cal1.get ( Calendar.MONTH ) == cal2.get ( Calendar.MONTH ) );
    }

    /**
     * 判刑两个时间前后
     *
     * @param start：开始时间
     * @param end：结束时间
     * @return：true表示，前面小于后面，后面大
     */
    public static boolean isAfter ( Date start, Date end ) {
        if ( start == null || end == null ) {
            return false;
        }
        if ( start.compareTo ( end ) < 0 ) {
            return true;
        }
        return false;
    }

    /**
     * 获取一个Date中的月份
     *
     * @param date
     * @return
     */
    public static int getMonth ( Date date ) {
        Calendar calendar = Calendar.getInstance ();
        calendar.setTime ( date );
        int month = calendar.get ( Calendar.MONTH ) + 1; // Calendar.MONTH 从 0 开始
        return month;
    }


    /**
     * 通过给定一个月份的整数，设置每个月的1号
     *
     * @param month：月份，1就是1月份
     * @return
     */
    public static Date setDateByMonth ( int month ) {
        if ( month < 1 ) {
            return null;
        }
        Calendar calendar = Calendar.getInstance ();
        calendar.set ( Calendar.DAY_OF_MONTH, 1 );
        calendar.set ( Calendar.MONTH, month - 1 );
        // 设置时分秒为0
        calendar.set ( Calendar.HOUR_OF_DAY, 0 );
        calendar.set ( Calendar.MINUTE, 0 );
        calendar.set ( Calendar.SECOND, 0 );
        calendar.set ( Calendar.MILLISECOND, 0 );
        // 获取第一天的Date对象
        Date date = calendar.getTime ();
        return date;
    }


    /**
     * 检查一个字符串最后一位是数字还是字母或者其他
     *
     * @param string
     * @return: 1）返回1表示最后一位是数字
     * 2）返回2表示最后一位是字母
     * 3）返回3表示以最后一位是其他
     * 4）返回-1表示字符串为空
     */
    public static int checkEnd ( String string ) {
        if ( string == null || string.isEmpty () ) {
            return - 1;
        }
        if ( string.matches ( ".*\\d$" ) ) {
            return 1;
        }
        if ( string.matches ( ".*[a-zA-Z]$" ) ) {
            return 2;
        }
        return 3;
    }

    /**
     * 生成token
     *
     * @return
     */
    public static String getToken () {
        return UUID.randomUUID ().toString ();
    }


    /***
     * MD5加密（生成唯一的MD5值）
     * @param key
     * @return
     * @throws Exception
     */
    public static String MD5Util ( String key ) {
        /*
         * 加密需要使用JDK中提供的类
         */
        StringBuffer sb = new StringBuffer ();
        try {
            MessageDigest digest = MessageDigest.getInstance ( "MD5" );
            byte[] bs = digest.digest ( key.getBytes () );
            /*
             *  加密后的数据是-128 到
             *  127 之间的数字，这个数字也不安全。
             *   取出每个数组的某些二进制位进行某些运算，得到一个具体的加密结果
             *   0000 0011 0000 0100 0010 0000 0110 0001
             *  &0000 0000 0000 0000 0000 0000 1111 1111
             *  ---------------------------------------------
             *   0000 0000 0000 0000 0000 0000 0110 0001
             *   把取出的数据转成十六进制数
             */
            for ( byte b : bs ) {
                int x = b & 255;
                String s = Integer.toHexString ( x );
                if ( x > 0 && x < 16 ) {
                    sb.append ( "0" );
                    sb.append ( s );
                } else {
                    sb.append ( s );
                }
            }
        } catch ( Exception e ) {
            System.out.println ( "加密失败" );
        }
        return sb.toString ();
    }

    /**
     * 时间戳转Date
     *
     * @param timeStamp
     * @return
     */
    public static Date parseTimeStamp ( long timeStamp ) {
        Date date = new Date ( timeStamp );
        return date;
    }

    /**
     * JSON数组转集合
     *
     * @param jsonArray
     * @return
     */
    public static List<String> parseArray ( JSONArray jsonArray ) {
        List<String> list = new ArrayList<> ();
        for ( int i = 0; i < jsonArray.size (); i++ ) {
            if ( jsonArray.getString ( i ) != null && ! "null".equals ( jsonArray.getString ( i ) ) ) {
                list.add ( String.valueOf ( jsonArray.get ( i ) ) );
            } else {
                list.add ( "0" );
            }
        }
        return list;
    }


    /**
     * 计算两个时间差（h）
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static Double timeDifference ( Date startDate, Date endDate ) {
        if ( startDate == null || endDate == null ) {
            return 0.0;
        }
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime () - startDate.getTime ();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        long sec = diff % nd % nh % nm / ns;
        // 计算为以小时为单位的小数时间
        double timeout = 0;
        if ( day > 0 ) {
            timeout += ( day * 24 );
        }
        if ( hour > 0 ) {
            timeout += hour;
        }
        if ( min > 0 ) {
            timeout += ( 1.0 * min / 60 );
        }
        timeout += ( 1.0 * sec / 3600 );
        BigDecimal two11 = new BigDecimal ( timeout );
        timeout = two11.setScale ( 2, BigDecimal.ROUND_HALF_UP ).doubleValue ();
        return timeout;
    }


}
